﻿using SQLDeploy.Data.Internal;
using SQLDeploy.Utils;
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Input;
using System.Xml.Serialization;

namespace SQLDeploy.Data.Files
{
    [XmlRoot("Environments")]
    [Serializable()]
    public class Connections : NotifyPropertyChanged
    {
        private ObservableCollection<Environments.Environment> _Environments = new ObservableCollection<Environments.Environment>();

        public ObservableCollection<Environments.Environment> Environments
        {
            get { return _Environments; }
            set
            {
                _Environments = value;
                OnPropertyChanged("Environments");
            }
        }


        public void SaveToFile(string fileName)
        {
            Check.notNullOrEmpty(fileName, "fileName");
            using (StreamWriter sw = new StreamWriter(fileName, false))
            {
                XmlSerializer xml = new XmlSerializer(typeof(Connections));
                xml.Serialize(sw, this);
                sw.Close();
            }
        }

        public static Connections LoadFromFile(string fileName)
        {
            Check.notNullOrEmpty(fileName, "fileName");
            Check.isTrue(File.Exists(fileName), "File Not Found [" + fileName + "]");
            Connections obj;
            FileStream inStream = new FileStream(fileName, FileMode.Open);
            XmlSerializer xml = new XmlSerializer(typeof(Connections));

            obj = (Connections)xml.Deserialize(inStream);
            inStream.Close();
            return obj;
        }

        public bool NameExists(string name)
        {
            Check.notNull(name);
            StringComparer sc = Internal.Shared.DefaultStringComparer();
            foreach (Environments.Environment env in _Environments)
            {
                if (sc.Equals(name, env.Name))
                    return true;
            }
            return false;
        }

        [XmlIgnore]
        public ICommand CreateEnvironmnetCommand
        {
            get { return new CreateEnvironmentCommand(this); }
        }

        [XmlIgnore]
        public ICommand RemoveEnvironmentCommand
        {
            get { return new RemoveEnvironmentCommand(this); }
        }
       
    }

    internal class CreateEnvironmentCommand : ICommand
    {
        private Connections _Connections;

        internal CreateEnvironmentCommand(Connections connections)
        {
            Check.notNull(connections);
            _Connections = connections;
        }

        public bool CanExecute(object parameter)
        {
            try
            {
                if (!(parameter is string))
                    return false;

                string name = (string)parameter;
                if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
                    return false;

                return !_Connections.NameExists(name);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message, e);
            }
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            if (!(parameter is string))
                throw new ArgumentException();

            string name = (string)parameter;
            if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
                throw new ArgumentException();

            if (!_Connections.NameExists(name))
            {
                Environments.Environment env = new Environments.Environment();
                env.Name = name;
                _Connections.Environments.Add(env);
            }

        }
    }

    internal class RemoveEnvironmentCommand : ICommand
    {
        private Connections _Connections;

        internal RemoveEnvironmentCommand(Connections connections)
        {
            Check.notNull(connections);
            _Connections = connections;
        }

        public bool CanExecute(object parameter)
        {
            try
            {
                if (!(parameter is string))
                    return false;

                string name = (string)parameter;
                if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
                    return false;

                return _Connections.NameExists(name);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message, e);
            }
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            if (!(parameter is string))
                throw new ArgumentException();

            string name = (string)parameter;
            if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
                throw new ArgumentException();

            if (_Connections.NameExists(name))
            {
                StringComparer sc = Internal.Shared.DefaultStringComparer();
                foreach (Environments.Environment env in _Connections.Environments)
                {
                    if (sc.Equals(env.Name, name))
                    {
                        _Connections.Environments.Remove(env);
                        return;
                    }
                }
            }
        }
    }
}
